﻿using System;

namespace Com.Lancetinc.Evs.Helpers
{
    public static class ArrayHelper
    {
        /// <summary>
        /// 判断数组是否想等。
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="arg1">数组1</param>
        /// <param name="arg2">数组2</param>
        /// <returns>true:相等，false:不相等</returns>
        public static bool AreEqual<T>(T[] arg1, T[] arg2) where T : IEquatable<T>
        {
            int arg1Len = arg1 != null ? arg1.Length : 0;
            int arg2Len = arg2 != null ? arg2.Length : 0;
            if (arg1Len != arg2Len)
                return false;
            if (arg1Len == 0)
                return true;

            for (int i = 0; i < arg1Len; i++)
                if (!arg1[i].Equals(arg2[i]))
                    return false;
            return true;
        }

        /// <summary>
        /// 判断数组的数组是否想等。
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="arg1">数组1</param>
        /// <param name="arg2">数组2</param>
        /// <returns>true:相等，false:不相等</returns>
        public static bool AreEqual<T>(T[][] arg1, T[][] arg2) where T : IEquatable<T>
        {
            int arg1Len = arg1 != null ? arg1.Length : 0;
            int arg2Len = arg2 != null ? arg2.Length : 0;
            if (arg1Len != arg2Len)
                return false;
            if (arg1Len == 0)
                return true;

            for (int i = 0; i < arg1Len; i++)
                if (!AreEqual(arg1[i], arg2[i]))
                    return false;

            return true;
        }

        /// <summary>
        /// 判断数组的数组的数组是否想等。
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="arg1">数组1</param>
        /// <param name="arg2">数组2</param>
        /// <returns>true:相等，false:不相等</returns>
        public static bool AreEqual<T>(T[][][] arg1, T[][][] arg2) where T : IEquatable<T>
        {
            int arg1Len = arg1 != null ? arg1.Length : 0;
            int arg2Len = arg2 != null ? arg2.Length : 0;
            if (arg1Len != arg2Len)
                return false;
            if (arg1Len == 0)
                return true;

            for (int i = 0; i < arg1Len; i++)
                if (!AreEqual(arg1[i], arg2[i]))
                    return false;

            return true;
        }

        /// <summary>
        /// 初始化 数组的数组
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="len1">数组的维数</param>
        /// <param name="len2">数组的数组的维数</param>
        /// <returns>数组的数组</returns>
        public static T[][] Initalize<T>(int len1, int len2)
        {
            T[][] result = new T[len1][];
            for (int i = 0; i < len1; i++)
                result[i] = new T[len2];
            return result;
        }

        /// <summary>
        /// 初始化 数组的数组的数组
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="len1">数组的维数</param>
        /// <param name="len2">数组的数组的维数</param>
        /// <param name="len3">数组的数组的数组的维数</param>
        /// <returns>数组的数组的数组</returns>
        public static T[][][] Initalize<T>(int len1, int len2, int len3)
        {
            T[][][] result = new T[len1][][];
            for (int i = 0; i < len1; i++)
                result[i] = Initalize<T>(len2, len3);
            return result;
        }

        /// <summary>
        /// 2维数组 转化为 数组的数组
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="values">2维数组</param>
        /// <returns>数组的数组</returns>
        public static T[][] Convert2<T>(T[,] values)
        {
            if (values == null)
                return null;
            var len1 = values.GetLength(0);
            var len2 = values.GetLength(1);
            T[][] result = new T[len1][];
            for (int i = 0; i < len1; i++)
            {
                result[i] = new T[len2];
                for (int j = 0; j < len2; j++)
                    result[i][j] = values[i, j];
            }
            return result;
        }

        /// <summary>
        /// 3维数组 转化为 数组的数组的数组
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="values">3维数组</param>
        /// <returns>数组的数组的数组</returns>
        public static T[][][] Convert2<T>(T[,,] values)
        {
            if (values == null)
                return null;
            var len1 = values.GetLength(0);
            var len2 = values.GetLength(1);
            var len3 = values.GetLength(2);
            T[][][] result = new T[len1][][];
            for (int i = 0; i < len1; i++)
            {
                result[i] = new T[len2][];
                for (int j = 0; j < len2; j++)
                {
                    result[i][j] = new T[len3];
                    for (int k = 0; k < len3; k++)
                        result[i][j][k] = values[i, j, k];
                }
            }
            return result;
        }

        /// <summary>
        /// 数组的数组 转化为 2维数组。
        /// （前提：数组的数组的维数必须一致）
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="values">数组的数组</param>
        /// <returns>2维数组</returns>
        public static T[,] Convert1<T>(T[][] values)
        {
            if (values == null) return null;
            int len1 = values.Length;
            if (len1 == 0) return null;
            int len2 = values[0].Length;

            T[,] result = new T[len1, len2];
            for (int i = 0; i < len1; i++)
            {
                for (int j = 0; j < len2; j++)
                    result[i, j] = values[i][j];
            }
            return result;
        }

        /// <summary>
        /// 数组的数组的数组 转化 为 3维数组。
        /// （前提：数组的数组的维数必须一致）
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="values">数组的数组的数组</param>
        /// <returns>3维数组</returns>
        public static T[,,] Convert1<T>(T[][][] values)
        {
            if (values == null) return null;
            int len1 = values.Length;
            if (len1 == 0) return null;
            int len2 = values[0].Length;
            if (len2 == 0) return null;
            int len3 = values[0][0].Length;

            T[,,] result = new T[len1, len2, len3];
            for (int i = 0; i < len1; i++)
            {
                for (int j = 0; j < len2; j++)
                    for (int k = 0; k < len3; k++)
                        result[i, j, k] = values[i][j][k];
            }
            return result;
        }

        /// <summary>
        /// 拷贝数组的数组的数组
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="values">数组的数组的数组</param>
        /// <returns>拷贝的数组的数组的数组</returns>
        public static T[][][] DeepClone<T>(T[][][] values)
        {
            if (values == null)
                return null;

            T[][][] results = new T[values.Length][][];
            for (int i = 0; i < values.Length; i++)
                results[i] = DeepClone(values[i]);
            return results;
        }

        /// <summary>
        /// 拷贝数组的数组
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="values">数组的数组</param>
        /// <returns>拷贝的数组的数组</returns>
        public static T[][] DeepClone<T>(T[][] values)
        {
            if (values == null)
                return null;

            T[][] results = new T[values.Length][];
            for (int i = 0; i < values.Length; i++)
                results[i] = DeepClone(values[i]);
            return results;
        }

        /// <summary>
        /// 拷贝数组
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="values">数组</param>
        /// <returns>拷贝的数组</returns>
        public static T[] DeepClone<T>(T[] values) 
        {
            if (values == null) 
                return null;
            T[] results = new T[values.Length];
            Array.Copy(values, results, values.Length);
            return results;
        }

        public static T[] SubArray<T>(T[] data, int index, int length)
        {
            var result = new T[length];
            Array.Copy(data, index, result, 0, length);
            return result;
        }
    }
}
